﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YJKGeometryFuncs;

namespace YJKArchUtils.StructurePoleSuit
{
	public class WallInfoHandler
	{
		public static List<ColumnProfilePart> MakeLstClolumnProfilePart(List<WallInfos> inputLstWallInfos, double useExtendLength)
		{
			List<ColumnProfilePart> list = new List<ColumnProfilePart>();
			int num = 1;
			foreach (WallInfos wallInfos in inputLstWallInfos)
			{
				XYZ ptPositiveStart = null;
				XYZ ptPositiveEnd = null;
				XYZ ptNegativeStart = null;
				XYZ ptNegativeEnd = null;
				WallInfoHandler.GetOffsetCurveInfo(wallInfos, ref ptPositiveStart, ref ptPositiveEnd, ref ptNegativeStart, ref ptNegativeEnd);
				ColumnProfilePart item = new ColumnProfilePart(wallInfos.Id, wallInfos.Start, wallInfos.End, wallInfos.Bugle, ptPositiveStart, ptPositiveEnd, ptNegativeStart, ptNegativeEnd, false, num, useExtendLength, true);
				num++;
				list.Add(item);
			}
			return list;
		}

		public static void MakeWallInfo(List<Element> inputLstElement, ref List<Element> lstFindWalls, ref List<WallInfos> lstFindWallInfos, IfWallMakeWallInfoDelegate isWallInfo = null)
		{
			foreach (Element element in ((IEnumerable<Element>)inputLstElement))
			{
				if (element.GetType() == typeof(Wall))
				{
					Wall wall = element as Wall;
					if (isWallInfo == null || isWallInfo(wall))
					{
						Curve curve = (wall.Location as LocationCurve).Curve;
						XYZ hyendPoint;
						XYZ hyendPoint2;
						double bugle;
						if (curve.GetType() == typeof(Arc))
						{
							Arc arc = curve as Arc;
							XYZ center = arc.Center;
							if (arc.Normal.IsAlmostEqualTo(XYZ.BasisZ, 0.0001))
							{
								hyendPoint = curve.GetEndPoint(0);
								hyendPoint2 = curve.GetEndPoint(1);
								bugle = Geometry.GetBulge(hyendPoint, hyendPoint2, center, true);
							}
							else
							{
								hyendPoint = curve.GetEndPoint(1);
								hyendPoint2 = curve.GetEndPoint(0);
								bugle = Geometry.GetBulge(hyendPoint, hyendPoint2, center, true);
							}
						}
						else
						{
							hyendPoint = curve.GetEndPoint(0);
							hyendPoint2 = curve.GetEndPoint(1);
							bugle = 0.0;
						}
						WallInfos item = new WallInfos(WallInfoHandler.To2D(hyendPoint), WallInfoHandler.To2D(hyendPoint2), bugle, wall.Width, wall.Id, wall.Id);
						lstFindWallInfos.Add(item);
						lstFindWalls.Add(wall);
					}
				}
			}
		}

		public static void SplitWallInfo(ExternalCommandData inputRevitData, ref List<WallInfos> inputWallInfoLst)
		{
			for (int i = 0; i < inputWallInfoLst.Count; i++)
			{
				bool flag = false;
				WallInfos wallInfos = inputWallInfoLst[i];
				List<WallInfos> list = new List<WallInfos>();
				int j = i + 1;
				while (j < inputWallInfoLst.Count)
				{
					WallInfos wallInfos2 = inputWallInfoLst[j];
					list.Clear();
					List<WallInfos> collection = new List<WallInfos>();
					if (wallInfos.SplitTest(wallInfos2, inputRevitData.Application.Application, ref list))
					{
						flag = true;
						if (wallInfos2.SplitTest(wallInfos, inputRevitData.Application.Application, ref collection))
						{
							inputWallInfoLst.RemoveAt(j);
							inputWallInfoLst.AddRange(collection);
							break;
						}
						break;
					}
					else
					{
						if (wallInfos2.SplitTest(wallInfos, inputRevitData.Application.Application, ref collection))
						{
							inputWallInfoLst.RemoveAt(j);
							inputWallInfoLst.AddRange(collection);
						}
						j++;
					}
				}
				if (flag)
				{
					inputWallInfoLst.RemoveAt(i);
					inputWallInfoLst.AddRange(list);
					i--;
				}
			}
		}

		public static void OffsetLine(XYZ ptStart, XYZ ptEnd, double offset, ref XYZ ptOffsetStart, ref XYZ ptOffsetEnd)
		{
			XYZ xyz = Geometry.RotateTo((ptEnd - ptStart).Normalize(), Math.PI*.5, XYZ.BasisZ) * offset;
			ptOffsetStart = ptStart + xyz;
			ptOffsetEnd = ptEnd + xyz;
		}

		private static XYZ To2D(XYZ pt)
		{
			return new XYZ(pt.X, pt.Y, 0.0);
		}

		private static void GetOffsetCurveInfo(WallInfos wallInfo, ref XYZ ptPositiveStart, ref XYZ ptPositiveEnd, ref XYZ ptNegativeStart, ref XYZ ptNegativeEnd)
		{
			if (Geometry.IsEqual(wallInfo.Bugle, 0.0))
			{
				WallInfoHandler.OffsetLine(wallInfo.Start, wallInfo.End, -wallInfo.Thickness / 2.0, ref ptPositiveStart, ref ptPositiveEnd);
				WallInfoHandler.OffsetLine(wallInfo.Start, wallInfo.End, wallInfo.Thickness / 2.0, ref ptNegativeStart, ref ptNegativeEnd);
				return;
			}
			WallInfoHandler.OffsetArc(wallInfo.Start, wallInfo.End, wallInfo.Bugle, wallInfo.Thickness / 2.0, ref ptPositiveStart, ref ptPositiveEnd);
			WallInfoHandler.OffsetArc(wallInfo.Start, wallInfo.End, wallInfo.Bugle, -wallInfo.Thickness / 2.0, ref ptNegativeStart, ref ptNegativeEnd);
		}

		private static void OffsetArc(XYZ ptStart, XYZ ptEnd, double bugle, double offset, ref XYZ ptOffsetStart, ref XYZ ptOffsetEnd)
		{
			XYZ xyz = null;
			Geometry.GetCenterWithBulge(ptStart, ptEnd, bugle, ref xyz);
			double num = xyz.DistanceTo(ptStart) + offset;
			XYZ xyz2 = (ptStart - xyz).Normalize() * num;
			XYZ xyz3 = (ptEnd - xyz).Normalize() * num;
			ptOffsetStart = xyz + xyz2;
			ptOffsetEnd = xyz + xyz3;
		}
	}
}
